﻿using Ganjine.Common;
using Ganjine.DataModel;
using Ganjine_Windows10;
using Ganjine_Windows10.Common;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage;
using Windows.UI;
using Windows.UI.Core;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Shapes;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace Ganjine
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        private readonly string defaultPoetOrder = "{\"2\":0,\"3\":1,\"4\":2,\"5\":3,\"6\":4,\"7\":5,\"8\":6,\"9\":7,\"10\":8,\"11\":9,\"12\":10,\"13\":11,\"14\":12,\"15\":13,\"27\":14,\"28\":15,\"29\":16,\"16\":17,\"35\":18,\"17\":19,\"501\":20,\"502\":21,\"503\":22,\"504\":23,\"506\":24,\"612\":25,\"701\":26,\"18\":27,\"19\":28,\"20\":29,\"21\":30,\"22\":31,\"23\":32,\"24\":33,\"25\":34,\"26\":35,\"30\":36,\"31\":37,\"32\":38,\"33\":39,\"34\":40,\"37\":41,\"38\":42,\"39\":43,\"40\":44,\"41\":45,\"42\":46,\"43\":47,\"44\":48,\"45\":49,\"46\":50,\"47\":51,\"48\":52,\"49\":53,\"50\":54,\"51\":55,\"52\":56,\"53\":57,\"54\":58,\"55\":59,\"56\":60}";
        private ObservableDictionary defaultViewModel = new ObservableDictionary();
        ObservableCollection<PoetItem> poetsCollection;
        bool isNavigatedBack = false;

        public MainPage()
        {
            this.InitializeComponent();
        }

        /// <summary>
        /// Gets the DefaultViewModel. This can be changed to a strongly typed view model.
        /// </summary>
        public ObservableDictionary DefaultViewModel
        {
            get { return this.defaultViewModel; }
        }

        private void PhoneSearchHardwareBackButtonPressed(object sender, BackRequestedEventArgs e)
        {
            e.Handled = true;
            BackToggle_Click(sender, new RoutedEventArgs());
        }

        private void SearchToggle_Click(object sender, RoutedEventArgs e)
        {
            headerText.Visibility = Visibility.Collapsed;
            SearchToggle.Visibility = Visibility.Collapsed;
            BackToggle.Visibility = Visibility.Visible;
            SearchBar.Visibility = Visibility.Visible;

            SearchTextBox.Focus(FocusState.Pointer);
            PhoneMainContent.Visibility = Visibility.Collapsed;
            PhoneCommandBar.Visibility = Visibility.Collapsed;

            SystemNavigationManager.GetForCurrentView().BackRequested += PhoneSearchHardwareBackButtonPressed;
        }

        private void BackToggle_Click(object sender, RoutedEventArgs e)
        {
            headerText.Visibility = Visibility.Visible;
            SearchToggle.Visibility = Visibility.Visible;
            BackToggle.Visibility = Visibility.Collapsed;
            SearchBar.Visibility = Visibility.Collapsed;

            SearchTextBox.Text = "";
            PhoneMainContent.Visibility = Visibility.Visible;
            PhoneCommandBar.Visibility = Visibility.Visible;

            SystemNavigationManager.GetForCurrentView().BackRequested -= PhoneSearchHardwareBackButtonPressed;
        }

        private async void Page_Loaded(object sender, RoutedEventArgs e)
        {
            SetSearchButtonOpacity();

            SetTitleAndFrameColor();


            await CopyDatabaseAsync();
            await App.dataSource.InitializeFavorites();

            PhoneMainContentPivot.IsEnabled = true;

            LoadingRing.Visibility = Visibility.Collapsed;

            //Create connection with database
            App.dataSource.CheckDBConnection();

            if (!this.defaultViewModel.ContainsKey("Poets"))
            {
                //Read list of poets.
                Dictionary<int, int> orders;
                poetsCollection = App.dataSource.GetListOfPoets();


                var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;

                if (localSettings.Values["poetOrders"] == null) //Default order
                {
                    localSettings.Values["poetOrders"] = defaultPoetOrder;
                }
                orders = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<int, int>>(localSettings.Values["poetOrders"].ToString());

                foreach (var item in poetsCollection)
                {
                    item.OrderID = orders[item.PoetID];
                }

                poetsCollection = new ObservableCollection<PoetItem>(poetsCollection.OrderBy(a => a.OrderID));

                poetsCollection.CollectionChanged += PoetsCollection_CollectionChanged;

                this.defaultViewModel["Poets"] = poetsCollection;



                /* !!!    try { searchSource.SelectedIndex = 0; }
                    catch { } */

                await App.dataSource.InitializeSettings();
            }


            if (isNavigatedBack)
            {
                CorrectScrollPosition();
                await Task.Delay(50);
                CorrectScrollPosition();

                isNavigatedBack = false;
            }


            /*

            await App.dataSource.InitializeFavorites();
            List<PoemItem> ppa = new List<PoemItem>();
            ppa.AddRange(App.favorites);
            this.defaultViewModel["Favs"] = ppa;

            try
            {
                if (ppa.Count == 0)
                {
                    NoFavorites.Visibility = Windows.UI.Xaml.Visibility.Visible;
                }
                else
                {
                    NoFavorites.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
                }
            }
            catch { }

            initProgress.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
            */
        }

        private void CorrectScrollPosition()
        {
            var gridView = VisualChildFinder.FindVisualChild<ScrollViewer>(PoetsGridView);
            var listView = VisualChildFinder.FindVisualChild<ScrollViewer>(PoetsListView);

            if (gridView != null)
                gridView.ChangeView(gridView.HorizontalOffset, App.scrollPosition["MainPageGrid"], gridView.ZoomFactor, true);
            if (listView != null)
                listView.ChangeView(listView.HorizontalOffset, App.scrollPosition["MainPageList"], listView.ZoomFactor, true);
        }

        private void PoetsCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            Dictionary<int, int> orders = new Dictionary<int, int>();
            for (int i = 0; i < poetsCollection.Count; i++)
            {
                poetsCollection[i].OrderID = i;
                orders.Add(poetsCollection[i].PoetID, i);
            }
            var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
            localSettings.Values["poetOrders"] = Newtonsoft.Json.JsonConvert.SerializeObject(orders);
        }

        private void SetTitleAndFrameColor()
        {
            var view = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView();

            SolidColorBrush headerBrush = Header.Background as SolidColorBrush;
            Frame.Background = Header.Background;

            view.TitleBar.BackgroundColor = Color.FromArgb(headerBrush.Color.A, headerBrush.Color.R, headerBrush.Color.G, headerBrush.Color.B);
            view.TitleBar.ForegroundColor = Colors.Black;

            view.TitleBar.ButtonBackgroundColor = Color.FromArgb(headerBrush.Color.A, headerBrush.Color.R, headerBrush.Color.G, headerBrush.Color.B); ;
            view.TitleBar.ButtonForegroundColor = Colors.Black;

            view.TitleBar.ButtonHoverBackgroundColor = DarkenOrLightenColor(headerBrush.Color, 0.75);
            view.TitleBar.ButtonHoverForegroundColor = Colors.Black;

            view.TitleBar.ButtonPressedBackgroundColor = DarkenOrLightenColor(headerBrush.Color, 0.65);
            view.TitleBar.ButtonPressedForegroundColor = Colors.Black;

            view.TitleBar.ButtonInactiveBackgroundColor = Colors.DarkGray;
            view.TitleBar.ButtonInactiveForegroundColor = Colors.Gray;

            view.TitleBar.InactiveBackgroundColor = Colors.DarkGray;
            view.TitleBar.InactiveForegroundColor = Colors.Gray;
        }

        private Color? DarkenOrLightenColor(Color color, double ratio)
        {
            int a = (int)(color.A * ratio);
            int r = (int)(color.A * ratio);
            int g = (int)(color.A * ratio);
            int b = (int)(color.A * ratio);

            if (a < 0) a = 0;
            if (a > 255) a = 255;

            if (r < 0) r = 0;
            if (r > 255) r = 255;

            if (g < 0) g = 0;
            if (g > 255) g = 255;

            if (b < 0) b = 0;
            if (b > 255) b = 255;

            return Color.FromArgb((byte)a, (byte)r, (byte)g, (byte)b);

        }

        private async Task CopyDatabaseAsync()
        {
            if (App.conn != null)
            {
                return;
            }

            bool versionMismatch = false;
            bool isDatabaseExisting = false;
            StorageFile storageFile = null;
            StorageFile databaseFile;

            try
            {
                databaseFile = await Package.Current.InstalledLocation.GetFileAsync("ganjoor2.s3db");
            }
            catch (Exception ex)
            {
                throw new Exception("Couldn't get db file.", ex);
            }

            try
            {
                StorageFile versionFile = await ApplicationData.Current.LocalFolder.GetFileAsync("version.txt");
                StorageFile currentVersionFile = await Package.Current.InstalledLocation.GetFileAsync("version.txt");
                int version = int.Parse(await Windows.Storage.FileIO.ReadTextAsync(versionFile));
                int currentVersion = int.Parse(await Windows.Storage.FileIO.ReadTextAsync(currentVersionFile));
                if (version != currentVersion)
                {
                    versionMismatch = true;
                }
            }
            catch (Exception ex)
            {
                /*LoadingGrid.Visibility = Windows.UI.Xaml.Visibility.Visible;
                commandBar.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
                Hub.IsEnabled = false;*/

                versionMismatch = true;
            }

            try
            {
                storageFile = await ApplicationData.Current.LocalFolder.GetFileAsync("ganjoor2.s3db");
                if (versionMismatch)
                {
                    try
                    {
                        App.conn.Dispose();
                        await Task.Delay(TimeSpan.FromSeconds(0.5));
                    }
                    catch { }
                    await storageFile.DeleteAsync();
                }
                else
                {
                    isDatabaseExisting = true;
                    if ((await storageFile.GetBasicPropertiesAsync()).Size != (await databaseFile.GetBasicPropertiesAsync()).Size) //Size mismatch
                    {
                        versionMismatch = true;
                    }
                }
            }
            catch (Exception ex)
            {
                /*LoadingGrid.Visibility = Windows.UI.Xaml.Visibility.Visible;
                commandBar.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
                Hub.IsEnabled = false;*/

                isDatabaseExisting = false;
            }

            if (versionMismatch)
            {
                StorageFile currentVersionFile = await Package.Current.InstalledLocation.GetFileAsync("version.txt");

                //Delete old version file, if exists.
                try
                {
                    StorageFile vFile = await ApplicationData.Current.LocalFolder.GetFileAsync("version.txt");
                    await vFile.DeleteAsync();
                }
                catch
                {

                }

                await currentVersionFile.CopyAsync(ApplicationData.Current.LocalFolder);
                /*if (isDatabaseExisting == true)
                {
                    LoadingGrid.Visibility = Windows.UI.Xaml.Visibility.Visible;
                    commandBar.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
                    Hub.IsEnabled = false;
                    bool CriticalError = false;
                    
                    try
                    {
                        storageFile = null;
                        storageFile = await ApplicationData.Current.LocalFolder.GetFileAsync("ganjoor2.s3db");
                        await storageFile.DeleteAsync();
                    }
                    catch (Exception ex)
                    {
                        CriticalError = true;
                    }
                    if (CriticalError)
                    {
                        Hub.Visibility = Visibility.Collapsed;
                        LoadingGrid.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
                        MessageDialog md = new MessageDialog("مشکلی در راه‌اندازی اولیه‌ی برنامه پیش آمده است. با عرض پوزش، لطفاً برنامه را از گوشی خود پاک کرده و از نو نصب کنید.");
                        await md.ShowAsync();
                        App.Current.Exit();
                        return;
                    }
                    isDatabaseExisting = false;
                }*/
            }

            if (!isDatabaseExisting)
            {


                try
                {
                    //StorageFile newfile = await ApplicationData.Current.LocalFolder.CreateFileAsync("ganjoor2.s3db");
                    //await CopyBigFile(databaseFile, newfile, CancellationToken.None);
                    await databaseFile.CopyAsync(ApplicationData.Current.LocalFolder, "ganjoor2.s3db", NameCollisionOption.ReplaceExisting);
                }
                catch (Exception ex)
                {
                    throw new Exception("Couldn't copy database file to local cache folder.", ex);
                }
            }
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            var gridView = VisualChildFinder.FindVisualChild<ScrollViewer>(PoetsGridView);
            var listView = VisualChildFinder.FindVisualChild<ScrollViewer>(PoetsListView);
            if (gridView != null)
                App.scrollPosition["MainPageGrid"] = gridView.VerticalOffset;
            else
                App.scrollPosition["MainPageGrid"] = 0;

            if (listView != null)
                App.scrollPosition["MainPageList"] = listView.VerticalOffset;
            else
                App.scrollPosition["MainPageList"] = 0;

            base.OnNavigatedFrom(e);
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            if (e.NavigationMode == NavigationMode.Back)
                isNavigatedBack = true;
            base.OnNavigatedTo(e);
        }

        private void itemGridView_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (AppBarButtonSort.IsChecked == true)
                return;

            var poet = (PoetItem)(e.ClickedItem);
            DataBridge1 db = new DataBridge1()
            {
                id = poet.CatID,
                title = poet.PoetName,
                poetid = poet.PoetID,
            };
            Frame.Navigate(typeof(SectionPage), Newtonsoft.Json.JsonConvert.SerializeObject(db));
        }

        private void SortAppBarButton_Click(object sender, RoutedEventArgs e)
        {
            bool isChecked = (((AppBarToggleButton)sender).IsChecked == true);
            PoetsListView.CanReorderItems = isChecked;
            PoetsListView.CanDragItems = isChecked;
            PoetsListView.AllowDrop = isChecked;

            PhoneMainContentPivot.IsLocked = isChecked;

            if (isChecked)
            {
                PoetsListViewAnim.Begin();
            }
            else
            {
                PoetsListViewAnimReverse.Begin();
            }
        }


        private void SearchButton_Click(object sender, RoutedEventArgs e)
        {
            if (SearchTextBox.Text.Length >= App._minSearchTextLength)
                Frame.Navigate(typeof(Search), Newtonsoft.Json.JsonConvert.SerializeObject(new DataBridgeSearch(SearchTextBox.Text, -1)));
        }

        private void SearchTextBox_KeyUp(object sender, KeyRoutedEventArgs e)
        {
            if (e.Key == Windows.System.VirtualKey.Enter)
            {
                SearchButton_Click(sender, new RoutedEventArgs());
            }
        }


        private void KeyPress(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.CharacterReceivedEventArgs args)
        {
            if (FocusManager.GetFocusedElement() is TextBox)
                return;

            if ((SearchTextBox.FocusState == Windows.UI.Xaml.FocusState.Unfocused) &&
                (SearchBar.Visibility == Visibility.Visible))
            {
                Char c = Convert.ToChar(args.KeyCode);
                if (Char.IsLetterOrDigit(c))
                {
                    SearchTextBox.Text = c.ToString();
                    SearchTextBox.SelectionStart = SearchTextBox.Text.Length;
                    SearchTextBox.SelectionLength = 0;
                    SearchTextBox.Focus(FocusState.Programmatic);
                }
            }
        }


        private void KeyPressEventRegister()
        {
            if (SearchBar.Visibility == Visibility.Visible)
                Window.Current.CoreWindow.CharacterReceived += KeyPress;
            else
                Window.Current.CoreWindow.CharacterReceived -= KeyPress;
        }

        protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
        {
            Window.Current.CoreWindow.CharacterReceived -= KeyPress;
            poetsCollection.CollectionChanged -= PoetsCollection_CollectionChanged;

            base.OnNavigatingFrom(e);
        }

        private void pageRoot_GotFocus(object sender, RoutedEventArgs e)
        {
            KeyPressEventRegister();
        }

        private void pageRoot_LostFocus(object sender, RoutedEventArgs e)
        {
            //Window.Current.CoreWindow.CharacterReceived -= KeyPress;
            //System.Diagnostics.Debug.WriteLine("LostFocus");
        }

        private void Page_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            KeyPressEventRegister();
        }

        private void SetSearchButtonOpacity()
        {
            SearchButton.Opacity = (SearchTextBox.Text.Length >= App._minSearchTextLength) ? 1 : 0.3;
        }

        private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            SetSearchButtonOpacity();
        }

        private void SearchTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            if ((SearchBar.HorizontalAlignment == HorizontalAlignment.Stretch) &&
                (SearchButton.FocusState == FocusState.Unfocused))
                BackToggle_Click(sender, e);
        }

        private void FavItemView_ItemClick(object sender, ItemClickEventArgs e)
        {
            PoemItem pi = (PoemItem)e.ClickedItem;
            DataBridge2 db = new DataBridge2()
            {
                parentid = 0,
                id = pi.ID,
            };
            Frame.Navigate(typeof(ItemPage), Newtonsoft.Json.JsonConvert.SerializeObject(db));
        }

        /**
        private void ShowFavorites()
        {
            var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
            if (localSettings.Values["favOrderBy"] == null)
            {
                localSettings.Values["favOrderBy"] = 2;
            }

            List<PoemItem> ppa = new List<PoemItem>();
            ppa.AddRange(App.favorites);
            for (int i = 0; i < ppa.Count; i++)
                if ((int)localSettings.Values["favOrderBy"] == 1)
                    ppa[i].OrderID = i;
                else
                    ppa[i].OrderID = ppa[i].ID;

            var groupedFavorites = QKit.JumpList.JumpListHelper.ToGroups(ppa, x => x.OrderID, x => x.PoetName);

            this.defaultViewModel["Favorites"] = groupedFavorites;
        }
         /**/
    }
}
